﻿using System.Reflection;

namespace DynamicLogicExpression.Analyzer;

public class PropertyNavigationAnalyzer
{
    private static readonly IDictionary<string, PropertyNavigation> _navCache = new Dictionary<string, PropertyNavigation>();

    public static PropertyNavigation Analyze<T>(string nav)
    {
        if (_navCache.TryGetValue(nav, out var analyzedNav))
        {
            return analyzedNav;
        }

        var analyzingNav = DeepAnalyzeNavigation(typeof(T), nav);

        _navCache.Add(nav, analyzingNav);

        return analyzingNav;
    }

    private static PropertyNavigation DeepAnalyzeNavigation(Type type, string nav)
    {
        var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);

        if (nav.Contains('.'))
        {
            var firstDot = nav.IndexOf('.');
            var slice = nav[..firstDot];

            var prop = properties.FirstOrDefault(n => n.Name.Equals(slice, StringComparison.OrdinalIgnoreCase));

            return prop is null
                ? throw new InvalidOperationException($"无法解析属性{slice}")
                : new()
                {
                    Navigation = slice.ToLower(),
                    SubNavigation = DeepAnalyzeNavigation(prop.PropertyType, nav[(firstDot + 1)..]),
                    PropertyInfo = prop,
                };
        }
        else
        {
            var prop = properties.FirstOrDefault(n => n.Name.Equals(nav, StringComparison.OrdinalIgnoreCase));

            return prop is null
                ? throw new InvalidOperationException($"无法解析属性{nav}")
                : new()
                {
                    Navigation = nav.ToLower(),
                    PropertyInfo = prop,
                };
        }
    }
}